"""
发票解析
@author:yczha
"""

import os
import wx
from threading import Thread
from concurrent.futures import ThreadPoolExecutor, as_completed

from openpyxl import Workbook

from src.config import settings
from src.utils import user_info, get_allowed_files
from src.ui.transparent_stastictext import TransparentStaticText
from src.api.inv_parse import query_inv_parse as api_inv_parse


class InvParse(wx.Dialog):
    def __init__(self, parent):
        super(InvParse, self).__init__(parent, title='发票解析')
        panel = wx.Panel(self)
        back = wx.StaticBitmap(panel, bitmap=wx.Bitmap(
            os.path.join(settings.assets_dir, 'bg.png')))
        self.result = None  # 存储结果
        _, account = user_info()
        self.info_tst = TransparentStaticText(self, label=account)
        self.info_tst.SetFont(wx.Font(10, wx.FONTFAMILY_SWISS,
                              wx.FONTSTYLE_ITALIC, wx.FONTWEIGHT_LIGHT, False, 'Microsoft YaHei'))
        self.info_tst.SetForegroundColour((200, 200, 200))
        self.info_tst.SetPosition((10, 10))

        fee = TransparentStaticText(self, label='注：按文件收费，￥0.05/份', style=wx.TE_MULTILINE | wx.TE_RICH2)
        fee.SetFont(wx.Font(11, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_ITALIC,
                         wx.FONTWEIGHT_BOLD, False, 'Microsoft YaHei'))
        fee.SetForegroundColour((255, 0, 0))
        fee.SetPosition((50, 150))

        tip = f'''*功能：发票五要素解析，\n  包括：发票代码、号码、开票日期、校验码、开具金额\n\n*注意：1. 支持pdf电子版、扫描版；支持图片\n            2. 每个文件只能含有一张发票'''
        self.tip = TransparentStaticText(
            self, label=tip, style=wx.TE_MULTILINE | wx.TE_RICH2)
        self.tip.SetFont(wx.Font(11, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_ITALIC,
                         wx.FONTWEIGHT_LIGHT, False, 'Microsoft YaHei'))
        self.tip.SetForegroundColour((255, 255, 255))
        self.tip.SetPosition((50, 180))

        open_btn = wx.BitmapButton(back, bitmap=wx.Bitmap(
            os.path.join(settings.assets_dir, 'open-file.png')))
        open_btn.SetPosition((160, 80))
        open_btn.Bind(wx.EVT_BUTTON, self.open_file)

        panel.Fit()
        self.Fit()
        self.Centre()

    def open_file(self, e):
        dlg = wx.DirDialog(self, u"选择文件夹", style=wx.DD_DEFAULT_STYLE)
        if dlg.ShowModal() == wx.ID_OK:
            allowed_files = get_allowed_files(dlg.GetPath())
            if len(allowed_files) < 1:
                wx.MessageBox('所选目录没有有效文件', '提示', wx.OK | wx.ICON_WARNING)
                return
            task_queue = []
            with TaskProgressDialog(None, files=allowed_files, task_queue=task_queue) as dlg:
                dlg.ShowModal()
            if len(task_queue) < 1:
                wx.MessageBox('结果为空', '提示', wx.OK | wx.ICON_WARNING)
            with wx.MessageDialog(None, '解析完成，保存结果?', '保存文件', wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION) as dlg:
                if dlg.ShowModal() != wx.ID_YES:
                    return
            fdlg = wx.FileDialog(self, '保存结果', os.getcwd(
            ), '发票解析结果.xlsx', 'Excel file(*.xlsx)|*.xls', wx.FD_SAVE)
            if fdlg.ShowModal() != wx.ID_OK:
                return
            state, msg = self.write_to_excel(task_queue, fdlg.GetPath())
            if state:
                wx.MessageBox(msg, '提示', wx.OK | wx.ICON_INFORMATION)
            else:
                wx.MessageBox(msg, '错误', wx.OK | wx.ICON_ERROR)
            _, account = user_info()
            self.info_tst.SetLabel('')
            self.info_tst.SetLabel(account)

    def write_to_excel(self, task_data, path):
        wb = Workbook()
        ws = wb.active
        ws['A1'] = '文件名称'
        ws['B1'] = '文件路径'
        ws['C1'] = '发票代码'
        ws['D1'] = '发票号码'
        ws['E1'] = '开票日期'
        ws['F1'] = '开具金额'
        ws['G1'] = '校验码'
        ws['H1'] = '备注'
        for status, filename, inv in task_data:
            filename, filepath = os.path.basename(
                filename), os.path.dirname(filename)
            if status == 1000 and inv['inv_code'] and inv['inv_num']:
                inv_info = [inv['inv_code'], inv['inv_num'],
                            inv['inv_date'], inv['inv_money'], inv['inv_chk'], '']
            elif status == 1000:
                inv_info = ['', '', '', '', '', '无效发票文件或不支持的格式']
            else:
                inv_info = ['', '', '', '', '', str(inv)]
            info = [filename, filepath] + inv_info
            ws.append(info)
        try:
            wb.save(path)
            return True, '文件保存成功！'
        except Exception as e:
            return False, str(e)


class TaskProgressDialog(wx.Dialog):
    """进度条控制"""

    def __init__(self, parent, files, task_queue):
        super(TaskProgressDialog, self).__init__(parent, title='完成进度')

        self.task_queue = task_queue
        self.files = files

        panel = wx.Panel(self)
        self.back = wx.StaticBitmap(panel, bitmap=wx.Bitmap(
            os.path.join(settings.assets_dir, 'progress.png')))
        self.STOP_TASK = False
        self.gauge = wx.Gauge(self.back, range=len(files), size=(320, 20))
        self.gauge.SetPosition((20, 50))
        self.file_lab = TransparentStaticText(self.back, label='0.0%')
        self.file_lab.SetFont(wx.Font(12, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
                                      wx.FONTWEIGHT_LIGHT, False, 'Microsoft YaHei'))
        self.file_lab.SetForegroundColour((0, 0, 255))
        self.file_lab.SetPosition((350, 50))
        self.file_msg = TransparentStaticText(self.back, label='')
        self.file_msg.SetFont(wx.Font(12, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
                                      wx.FONTWEIGHT_LIGHT, False, 'Microsoft YaHei'))
        self.file_msg.SetForegroundColour((255, 255, 255))
        self.file_msg.SetPosition((100, 100))

        panel.Fit()
        self.Fit()
        self.Centre()
        self.SetMaxSize(self.GetSize())
        self.SetMinSize(self.GetSize())

        self.Bind(wx.EVT_CLOSE, self.OnExit)

        self.thread = Thread(target=self.run_tasks)
        self.thread.setDaemon(True)
        self.thread.start()

    def OnExit(self, evt):
        self.STOP_TASK = True
        self.DestroyLater()

    def update_process(self, msg, tip):
        if self.file_lab is not None:
            self.file_lab.SetLabel('')
        if self.file_msg is not None:
            self.file_msg.SetLabel('')

        self.file_lab = TransparentStaticText(self.back, label=msg)
        self.file_lab.SetFont(wx.Font(12, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
                                      wx.FONTWEIGHT_LIGHT, False, 'Microsoft YaHei'))
        self.file_lab.SetForegroundColour((0, 0, 255))
        self.file_lab.SetPosition((350, 50))

        self.file_msg = TransparentStaticText(self.back, label=tip)
        self.file_msg.SetFont(wx.Font(12, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
                                      wx.FONTWEIGHT_LIGHT, False, 'Microsoft YaHei'))
        self.file_msg.SetForegroundColour((255, 255, 255))
        self.file_msg.SetPosition((100, 100))

    def run_tasks(self):
        with ThreadPoolExecutor(max_workers=8) as pool:
            tasks = [pool.submit(api_inv_parse, file_) for file_ in self.files]
            for i, t in enumerate(as_completed(tasks)):
                if self.STOP_TASK:
                    return
                status, filename, data = t.result()
                self.task_queue.append([status, filename, data])
                wx.CallAfter(self.gauge.SetValue, i + 1)
                if status == 1000:
                    msg = f'{round((i + 1) / len(self.files) * 100, 1)}%'
                    wx.CallAfter(self.gauge.SetValue, i + 1)
                    wx.CallAfter(self.file_lab.SetLabel, msg)
                    wx.CallAfter(
                        self.file_msg.SetLabel, f'解析文件：{os.path.basename(filename)}')
        wx.CallAfter(self.Destroy)


if __name__ == '__main__':
    app = wx.App()
    with InvParse(None) as dlg:
        dlg.ShowModal()
    app.MainLoop()
